#include "Bebete.h"
#include <stdlib.h>
#include <cassert>

/* initialisation de la bebete : 
 * dans la case de coordonnées (-1,0), 
 * niveau de vie 5, 
 * direction 1 (vers la droite)*/
void init_bebete (Sbebete* beb)
{
	(*beb).X=-1;
	(*beb).Y=0;
	(*beb).niveauvie=5;
	(*beb).directionbebete=1;
}

/* Cette fonction est un accesseur à la coordonnée X de la bébête :
 * AUCUN DE SES PARAMETRES NE POURRA ETRE MODIFIE APRES SON EXECUTION.
 * Elle prend en paramètre un pointeur sur une structure bebete.
 * Elle renvoie un entier correspondant à la coordonnée X de la bébête */
int get_Xbebete (const Sbebete* beb)
{
	return ((*beb).X);
}

/* Cette fonction est un accesseur à la coordonnée Y de la bébête :
 * AUCUN DE SES PARAMETRES NE POURRA ETRE MODIFIE APRES SON EXECUTION.
 * Elle prend en paramètre un pointeur sur une structure bebete.
 * Elle renvoie un entier correspondant à la coordonnée Y de la bébête */
int get_Ybebete (const Sbebete* beb)
{
	return ((*beb).Y);
}

/* Cette fonction est un accesseur au niveau de vie de la bebete : niveau entre 1 et 5 (0 la bebete est morte)
 * AUCUN DE SES PARAMETRES NE POURRA ETRE MODIFIE APRES SON EXECUTION.
 * Elle prend en paramètre un pointeur sur une structure bebete.
 * Elle renvoie un entier correspondant au niveau de vie de la bebete */
int get_niveauvie (const Sbebete* beb)
{
	return ((*beb).niveauvie);
}

/* Cette fonction est un accesseur à la direction de la bebete
 * 1 : vers la droite
 * 2 : vers la gauche
 * 3 : vers le haut
 * 4 : vers le bas
 * 5 : quand la bebete est arrivée au chateau
 * AUCUN DE SES PARAMETRES NE POURRA ETRE MODIFIE APRES SON EXECUTION.
 * Elle prend en paramètre un pointeur sur une structure bebete.
 * Elle renvoie un entier correspondant à la coordonnée X de la bébête */
int get_directionbebete (const Sbebete* beb)
{
	return ((*beb).directionbebete);
}


/* Cette procédure est un mutateur à la coordonnée X de la bébête.
 * ATTENTION, APRES SON EXECUTION, LES COORDONNES DE LA BEBETE SERA MODIFIE !
 * Elle prend en paramètres un pointeur sur une structure bebete et le nouveau X */
void set_Xbebete (Sbebete* beb, int nvoX)
{
	(*beb).X=nvoX;
}


/* Cette procédure est un mutateur à la coordonnée Y de la bébête.
 * ATTENTION, APRES SON EXECUTION, LES COORDONNEES DE LA BEBETE SERA MODIFIE !
 * Elle prend en paramètres un pointeur sur une structure bebete et le nouveau Y */
void set_Ybebete (Sbebete* beb, int nvoY)
{
	(*beb).Y=nvoY;
}

/* Fonction qui permet de calculer le nouveau X suivant la direction de la bebete à l'instant présent 
 * On teste seulement la droite et la gauche
 * attention : on ne pourra pas appeler cette fonction avec un pointeur null  */
int calculnouveauX (const Sbebete* beb)
{
	assert(beb!=NULL); // verifie qu'il y a bien une bebete
	int nvoX;
	
	if ((*beb).directionbebete == 5)
	{
		nvoX=0;
		return nvoX;
	}
	
	if ((*beb).directionbebete == 1)
	{
		nvoX = ((*beb).X)+1;
		return nvoX;
	}
	else
	{
		if ((*beb).directionbebete == 2)
		{
			nvoX = ((*beb).X)-1;
			return nvoX;
		}
		else
		{
			nvoX=(*beb).X;
			return nvoX;
		}
	}
}

/* Fonction qui permet de calculer le nouveau Y suivant la direction de la bebete à l'instant présent 
 * On teste seulement le haut et le bas 
 * attention : on ne pourra pas appeler cette fonction avec un pointeur null */
int calculnouveauY (const Sbebete* beb)
{
	assert(beb!=NULL); // verifie qu'il y a bien une bebete
	int nvoY;
	
	if ((*beb).directionbebete == 5)
	{
		nvoY=0;
		return nvoY;
	}
	
	if ((*beb).directionbebete == 4)
	{
		nvoY = ((*beb).Y)+1;
		return nvoY;
	}
	else
	{
		if ((*beb).directionbebete == 3)
		{
			nvoY = ((*beb).Y)-1;
			return nvoY;
		}
		else
		{
			nvoY=(*beb).Y;
			return nvoY;
		}
	}
}


/* Cette procédure est un mutateur au niveau de vie de la bebete.
 * ATTENTION, APRES SON EXECUTION, LE NIVEAU DE VIE DE LA BEBETE SERA MODIFIE !
 * Elle prend en paramètres un pointeur sur une structure bebete et le nouveau niveau de vie */
void set_niveauvie (Sbebete* beb, int nvoniveauvie)
{
	(*beb).niveauvie=nvoniveauvie;
}


/* Cette procédure est un mutateur à la direction de la bebete.
 * ATTENTION, APRES SON EXECUTION, LA DIRECTION DE LA BEBETE SERA MODIFIE !
 * Elle prend en paramètres un pointeur sur une structure bebete et la nouvelle direction */
void set_directionbebete (Sbebete* beb, int nvodirbb)
{
	(*beb).directionbebete=nvodirbb;
}



/* Fonction qui calcule la nouvelle direction de la bebete si elle est placée sur n'importe qu'elle case
 *  sauf les bords du terrain 
 * Elle prend en paramètre un pointeur sur une structure bebete et un pointeur sur une structure terrain
 * Elle renvoie un entier qui correspond à la nouvelle direction */
int calculnouvelledirection1 (const Sbebete* beb, const Sterrain* ter)
{
	int nvodirection;
	
	if ((*beb).directionbebete == 1)
	{
		if ((get_terrain((*beb).X+2, (*beb).Y, ter))==1)
		{
			nvodirection=1;
			return nvodirection;
		}
		else
		{
			if ((get_terrain((*beb).X+1, (*beb).Y+1, ter))==1)
			{
				nvodirection=4;
				return nvodirection;
			}
			else
			{
				nvodirection=3;
				return nvodirection;
			}
		}
	}
	else
	{
		if ((*beb).directionbebete == 2)
		{
			if ((get_terrain((*beb).X-2, (*beb).Y, ter))==1)
			{
				nvodirection=2;
				return nvodirection;
			}
			else
			{
				if ((get_terrain((*beb).X-1, (*beb).Y+1, ter))==1)
				{
					nvodirection=4;
					return nvodirection;
				}
				else
				{
					nvodirection=3;
					return nvodirection;
				}
			}
		}
		else
		{
			if ((*beb).directionbebete == 3)
			{
				if ((get_terrain((*beb).X, (*beb).Y-2, ter))==1)
				{
					nvodirection=3;
					return nvodirection;
				}
				else
				{
					if ((get_terrain((*beb).X-1, (*beb).Y-1, ter))==1)
					{
						nvodirection=2;
						return nvodirection;
					}
					else
					{
						nvodirection=1;
						return nvodirection;
					}
				}
			}
			else
			{
				if ((*beb).directionbebete == 4)
				{
					if ((get_terrain((*beb).X, (*beb).Y+2, ter))==1)
					{
						nvodirection=4;
						return nvodirection;
					}
					else
					{
						if ((get_terrain((*beb).X-1, (*beb).Y+1, ter))==1)
						{
							nvodirection=2;
							return nvodirection;
						}
						else
						{
							nvodirection=1;
							return nvodirection;
						}
					}
				}
			}
		}
	}
	return (0); // renvoi 0 si il y a une erreur
}	



/* Fonstion qui calcule la nouvelle direction de la bebete si celle ci est placer sur un bord du terrain 
 * Elle prend en paramètre un pointeur sur une structure bebete, un X, un Y 
 * et une structure sur un terrain 
 * Elle renvoie un entier qui correspond à la nouvelle direction */
int calculnouvelledirection (const Sbebete* beb, int nvoX, int nvoY, const Sterrain* ter)
{
	int nvodirection;
	
	if ((nvoX == 0) && (nvoY == 0)) // case en haut à gauche
	{
		if ((get_terrain(nvoX+1, nvoY, ter))==1)
		{
			nvodirection=1;
			return nvodirection;
		}
		else
		{
			nvodirection=4;
			return nvodirection;
		}
	}
	else if ((nvoX == get_longueur (ter)-1) && (nvoY == 0) ) // case en haut à droite
	{
		if ((*beb).directionbebete==1)
		{
			nvodirection=4;
			return nvodirection;
		}
		else 
		{
			nvodirection=2;
			return nvodirection;
		}
	}
	else if ((nvoX == 0) && (nvoY = get_hauteur (ter)-1) ) // case en bas à gauche
	{
		if ((*beb).directionbebete==4)
		{
			nvodirection=1;
			return nvodirection;
		}
		else 
		{
			nvodirection=3;
			return nvodirection;
		}
	}
	else if ( (nvoX == (get_longueur(ter)-1)) && (nvoY == (get_hauteur(ter)-1)) ) // case en bas à droite
	{
		nvodirection=5;
		return nvodirection;
	}
	else
	{
		if (nvoX == 0) // bord supérieur
		{
			if ((*beb).directionbebete==4)
			{
				if ((get_terrain(nvoX+1, nvoY, ter))==1)
				{
					nvodirection=1;
					return nvodirection;
				}
				else
				{
					nvodirection=4;
					return nvodirection;
				}
			}
			else
			{
				if ((*beb).directionbebete==2)
				{
					if ((get_terrain(nvoX, nvoY-1, ter))==1)
					{
						nvodirection=3;
						return nvodirection;
					}
					else
					{
						nvodirection=4;
						return nvodirection;
					}
				}
				else
				{
					if ((get_terrain(nvoX, nvoY-1, ter))==1)
					{
						nvodirection=3;
						return nvodirection;
					}
					else
					{
						nvodirection=1;
						return nvodirection;
					}
				}
			}
		}
		else
		{
			if (nvoY == 0) // bord gauche
			{
				if ((*beb).directionbebete==1)
				{
					if ((get_terrain(nvoX+1, nvoY, ter))==1)
					{
						nvodirection=1;
						return nvodirection;
					}
					else
					{
						nvodirection=4;
						return nvodirection;
					}
				}
				else
				{
					if ((*beb).directionbebete==2)
					{
						if ((get_terrain(nvoX, nvoY+1, ter))==1)
						{
							nvodirection=4;
							return nvodirection;
						}
						else
						{
							nvodirection=2;
							return nvodirection;
						}
					}
					else
					{
						if ((get_terrain(nvoX-1, nvoY, ter))==1)
						{
							nvodirection=2;
							return nvodirection;
						}
						else
						{
							nvodirection=1;
							return nvodirection;
						}
					}
				}
			}
			else
			{
				if (nvoX == get_longueur(ter)-1) // bord droit
				{
					if ((*beb).directionbebete==1)
					{
						if ((get_terrain(nvoX, nvoY-1, ter))==1)
						{
							nvodirection=3;
							return nvodirection;
						}
						else
						{
							nvodirection=4;
							return nvodirection;
						}
					}
					else
					{
						if ((*beb).directionbebete==4)
						{
							if ((get_terrain(nvoX-1, nvoY, ter))==1)
							{
								nvodirection=2;
								return nvodirection;
							}
							else
							{
								nvodirection=4;
								return nvodirection;
							}
						}
						else
						{
							if ((get_terrain(nvoX-1, nvoY, ter))==1)
							{
								nvodirection=2;
								return nvodirection;
							}
							else
							{
								nvodirection=3;
								return nvodirection;
							}
						}
					}
				}
				else
				{
					if (nvoY == get_hauteur(ter)-1) // bord inférieur
					{
						if ((*beb).directionbebete==1)
						{
							
							if ((get_terrain(nvoX, nvoY-1, ter))==1)
							{
								nvodirection=3;
								return nvodirection;
							}
							else
							{
								nvodirection=1;
								return nvodirection;
							}
						}
						else
						{
							if ((*beb).directionbebete==4)
							{
								if ((get_terrain(nvoX-1, nvoY, ter))==1)
								{
									nvodirection=2;
									return nvodirection;
								}
								else
								{
									nvodirection=1;
									return nvodirection;
								}
							}
							else
							{
								if ((get_terrain(nvoX-1, nvoY, ter))==1)
								{
									nvodirection=2;
									return nvodirection;
								}
								else
								{
									nvodirection=3;
									return nvodirection;
								}
							}
						}
					}
				}
			}
		}
	}
	return (0); // renvoi 0 si il y a une erreur
}

/* Cette fonction permet de deplacer une bebete
 * elle calcule d'abord la direction que la bebete aura dans la case suivante
 * puis elle deplace la bebete en metant a jour ses coordonnées 
 * Elle prend en paramètre un pointeur sur une structure bebete et un pointeur sur une structure terrain*/
void deplacerdunecase( Sbebete* beb, const Sterrain* ter)
{	
	int nvdir, nvX, nvY ;
	
	nvX = calculnouveauX (beb);
	nvY = calculnouveauY (beb);
	
	if ( (nvX==get_longueur(ter)) &&  (nvY==get_hauteur(ter)) )
	{
		nvX=0;
		nvY=0;
	}
	
	if ((nvX==0) || (nvY==0) || (nvX==get_longueur(ter)-1) || (nvY==get_hauteur(ter)-1))
	{
		nvdir=calculnouvelledirection(beb, nvX, nvY, ter);
	}
	else
	{
		nvdir=calculnouvelledirection1 (beb, ter);
	}
	
	set_Xbebete(beb, nvX);
	set_Ybebete(beb, nvY);
	set_directionbebete(beb, nvdir);
}
	
/* On enleve une vie a la bebete mais sans tester si elle est deja morte ou pas
 * Elle prend en paramètre un pointeur sur une structure bebete */

void pertedevie(Sbebete* beb)
{
	int nbvie;
	nbvie=get_niveauvie(beb);
	
	(*beb).niveauvie=nbvie-1;
}

	
